From 76bd51c23dad4ceb2d3b7677229aac117693b97c Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 7 Oct 2005 15:51:53 +0100 Subject: [PATCH] Change xs_read_watch interface to return a sized array (in userspace and in kernel). Add index macros (XS_WATCH_*) for accessing the array to allow for future expansion. Signed-off-by: Anthony Liguori --- .../drivers/xen/xenbus/xenbus_xs.c | 59 +++++++++++-------- tools/blktap/xenbus.c | 7 ++- tools/console/daemon/io.c | 7 ++- tools/python/xen/lowlevel/xs/xs.c | 7 ++- tools/xenstore/xenstored.h | 8 +++ tools/xenstore/xs.c | 33 ++++++++--- tools/xenstore/xs.h | 14 ++++- tools/xenstore/xs_test.c | 15 +++-- 8 files changed, 101 insertions(+), 49 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c index 50919961f4..763803297f 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c @@ -200,14 +200,9 @@ static char *join(const char *dir, const char *name) return buffer; } -char **xenbus_directory(const char *dir, const char *node, unsigned int *num) +static char **split(char *strings, unsigned int len, unsigned int *num) { - char *strings, *p, **ret; - unsigned int len; - - strings = xs_single(XS_DIRECTORY, join(dir, node), &len); - if (IS_ERR(strings)) - return (char **)strings; + char *p, **ret; /* Count the strings. */ *num = count_strings(strings, len); @@ -224,8 +219,21 @@ char **xenbus_directory(const char *dir, const char *node, unsigned int *num) strings = (char *)&ret[*num]; for (p = strings, *num = 0; p < strings + len; p += strlen(p) + 1) ret[(*num)++] = p; + return ret; } + +char **xenbus_directory(const char *dir, const char *node, unsigned int *num) +{ + char *strings; + unsigned int len; + + strings = xs_single(XS_DIRECTORY, join(dir, node), &len); + if (IS_ERR(strings)) + return (char **)strings; + + return split(strings, len, num); +} EXPORT_SYMBOL(xenbus_directory); /* Check if a path exists. Return 1 if it does. */ @@ -425,18 +433,19 @@ static int xs_watch(const char *path, const char *token) return xs_error(xs_talkv(XS_WATCH, iov, ARRAY_SIZE(iov), NULL)); } -static char *xs_read_watch(char **token) +static char **xs_read_watch(unsigned int *num) { enum xsd_sockmsg_type type; - char *ret; + char *strings; + unsigned int len; - ret = read_reply(&type, NULL); - if (IS_ERR(ret)) - return ret; + strings = read_reply(&type, &len); + if (IS_ERR(strings)) + return (char **)strings; BUG_ON(type != XS_WATCH_EVENT); - *token = ret + strlen(ret) + 1; - return ret; + + return split(strings, len, num); } static int xs_acknowledge_watch(const char *token) @@ -519,8 +528,8 @@ void reregister_xenbus_watches(void) static int watch_thread(void *unused) { for (;;) { - char *token; - char *node = NULL; + char **vec = NULL; + unsigned int num; wait_event(xb_waitq, xs_input_avail()); @@ -530,23 +539,23 @@ static int watch_thread(void *unused) */ down(&xenbus_lock); if (xs_input_avail()) - node = xs_read_watch(&token); + vec = xs_read_watch(&num); - if (node && !IS_ERR(node)) { + if (vec && !IS_ERR(vec)) { struct xenbus_watch *w; int err; - err = xs_acknowledge_watch(token); + err = xs_acknowledge_watch(vec[XS_WATCH_TOKEN]); if (err) printk(KERN_WARNING "XENBUS ack %s fail %i\n", - node, err); - w = find_watch(token); + vec[XS_WATCH_TOKEN], err); + w = find_watch(vec[XS_WATCH_TOKEN]); BUG_ON(!w); - w->callback(w, node); - kfree(node); - } else if (node) + w->callback(w, vec[XS_WATCH_PATH]); + kfree(vec); + } else if (vec) printk(KERN_WARNING "XENBUS xs_read_watch: %li\n", - PTR_ERR(node)); + PTR_ERR(vec)); up(&xenbus_lock); } } diff --git a/tools/blktap/xenbus.c b/tools/blktap/xenbus.c index 48b085c2fb..c9cbea5fb3 100644 --- a/tools/blktap/xenbus.c +++ b/tools/blktap/xenbus.c @@ -251,13 +251,14 @@ int xs_fire_next_watch(struct xs_handle *h) char *node = NULL; struct xenbus_watch *w; int er; + unsigned int num; - res = xs_read_watch(h); + res = xs_read_watch(h, &num); if (res == NULL) return -EAGAIN; /* in O_NONBLOCK, read_watch returns 0... */ - node = res[0]; - token = res[1]; + node = res[XS_WATCH_PATH]; + token = res[XS_WATCH_TOKEN]; er = xs_acknowledge_watch(h, token); if (er == 0) diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c index cde27b2dc7..24afe0b513 100644 --- a/tools/console/daemon/io.c +++ b/tools/console/daemon/io.c @@ -491,14 +491,15 @@ static void handle_xs(int fd) char **vec; int domid; struct domain *dom; + unsigned int num; - vec = xs_read_watch(xs); + vec = xs_read_watch(xs, &num); if (!vec) return; - if (!strcmp(vec[1], "domlist")) + if (!strcmp(vec[XS_WATCH_TOKEN], "domlist")) enum_domains(); - else if (sscanf(vec[1], "dom%u", &domid) == 1) { + else if (sscanf(vec[XS_WATCH_TOKEN], "dom%u", &domid) == 1) { dom = lookup_domain(domid); if (dom->is_dead == false) domain_create_ring(dom); diff --git a/tools/python/xen/lowlevel/xs/xs.c b/tools/python/xen/lowlevel/xs/xs.c index 186455f6f6..64a08e1892 100644 --- a/tools/python/xen/lowlevel/xs/xs.c +++ b/tools/python/xen/lowlevel/xs/xs.c @@ -462,19 +462,20 @@ static PyObject *xspy_read_watch(PyObject *self, PyObject *args, char **xsval = NULL; PyObject *token; int i; + unsigned int num; if (!xh) goto exit; if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec)) goto exit; Py_BEGIN_ALLOW_THREADS - xsval = xs_read_watch(xh); + xsval = xs_read_watch(xh, &num); Py_END_ALLOW_THREADS if (!xsval) { PyErr_SetFromErrno(PyExc_RuntimeError); goto exit; } - if (sscanf(xsval[1], "%li", (unsigned long *)&token) != 1) { + if (sscanf(xsval[XS_WATCH_TOKEN], "%li", (unsigned long *)&token) != 1) { PyErr_SetString(PyExc_RuntimeError, "invalid token"); goto exit; } @@ -487,7 +488,7 @@ static PyObject *xspy_read_watch(PyObject *self, PyObject *args, goto exit; } /* Create tuple (path, token). */ - val = Py_BuildValue("(sO)", xsval[0], token); + val = Py_BuildValue("(sO)", xsval[XS_WATCH_PATH], token); exit: if (xsval) free(xsval); diff --git a/tools/xenstore/xenstored.h b/tools/xenstore/xenstored.h index 3633e5eb74..a84018d8e7 100644 --- a/tools/xenstore/xenstored.h +++ b/tools/xenstore/xenstored.h @@ -86,4 +86,12 @@ struct xsd_sockmsg /* Generally followed by nul-terminated string(s). */ }; +/* FIXME we shouldn't have to declare this in two places, what's the right + way to share things between xenstored.h and xs.h? */ +enum xs_watch_type +{ + XS_WATCH_PATH = 0, + XS_WATCH_TOKEN, +}; + #endif /* _XENSTORED_H */ diff --git a/tools/xenstore/xs.c b/tools/xenstore/xs.c index a842a6e39c..4f21bbc590 100644 --- a/tools/xenstore/xs.c +++ b/tools/xenstore/xs.c @@ -449,25 +449,44 @@ bool xs_watch(struct xs_handle *h, const char *path, const char *token) * Returns array of two pointers: path and token, or NULL. * Call free() after use. */ -char **xs_read_watch(struct xs_handle *h) +char **xs_read_watch(struct xs_handle *h, unsigned int *num) { struct xsd_sockmsg msg; char **ret; + char *strings; + unsigned int num_strings, i; if (!read_all(h->fd, &msg, sizeof(msg))) return NULL; assert(msg.type == XS_WATCH_EVENT); - ret = malloc(sizeof(char *)*2 + msg.len); - if (!ret) + strings = malloc(msg.len); + if (!strings) return NULL; - ret[0] = (char *)(ret + 2); - if (!read_all(h->fd, ret[0], msg.len)) { - free_no_errno(ret); + if (!read_all(h->fd, strings, msg.len)) { + free_no_errno(strings); return NULL; } - ret[1] = ret[0] + strlen(ret[0]) + 1; + + num_strings = xs_count_strings(strings, msg.len); + + ret = malloc(sizeof(char*) * num_strings + msg.len); + if (!ret) { + free_no_errno(strings); + return NULL; + } + + ret[0] = (char *)(ret + num_strings); + memcpy(ret[0], strings, msg.len); + free(strings); + + for (i = 1; i < num_strings; i++) { + ret[i] = ret[i - 1] + strlen(ret[i - 1]) + 1; + } + + *num = num_strings; + return ret; } diff --git a/tools/xenstore/xs.h b/tools/xenstore/xs.h index bd4bcbd348..351f55a410 100644 --- a/tools/xenstore/xs.h +++ b/tools/xenstore/xs.h @@ -24,6 +24,14 @@ struct xs_handle; +/* FIXME we shouldn't have to declare this in two places, what's the right + way to share things between xenstored.h and xs.h? */ +enum xs_watch_type +{ + XS_WATCH_PATH = 0, + XS_WATCH_TOKEN, +}; + /* On failure, these routines set errno. */ /* Connect to the xs daemon. @@ -91,10 +99,10 @@ bool xs_watch(struct xs_handle *h, const char *path, const char *token); int xs_fileno(struct xs_handle *h); /* Find out what node change was on (will block if nothing pending). - * Returns array of two pointers: path and token, or NULL. - * Call free() after use. + * Returns array containing the path and token. Use XS_WATCH_* to access these + * elements. Call free() after use. */ -char **xs_read_watch(struct xs_handle *h); +char **xs_read_watch(struct xs_handle *h, unsigned int *num); /* Acknowledge watch on node. Watches must be acknowledged before * any other watches can be read. diff --git a/tools/xenstore/xs_test.c b/tools/xenstore/xs_test.c index e55057f572..00c7ba7bea 100644 --- a/tools/xenstore/xs_test.c +++ b/tools/xenstore/xs_test.c @@ -489,8 +489,11 @@ static void do_watch(unsigned int handle, const char *node, const char *token, /* Convenient for testing... */ if (swallow_event) { - char **vec = xs_read_watch(handles[handle]); - if (!vec || !streq(vec[0], node) || !streq(vec[1], token)) + unsigned int num; + char **vec = xs_read_watch(handles[handle], &num); + if (!vec || + !streq(vec[XS_WATCH_PATH], node) || + !streq(vec[XS_WATCH_TOKEN], token)) failed(handle); if (!xs_acknowledge_watch(handles[handle], token)) failed(handle); @@ -522,6 +525,7 @@ static void do_waitwatch(unsigned int handle) struct timeval tv = {.tv_sec = timeout_ms/1000, .tv_usec = (timeout_ms*1000)%1000000 }; fd_set set; + unsigned int num; if (xs_fileno(handles[handle]) != -2) { /* Manually select here so we can time out gracefully. */ @@ -537,16 +541,17 @@ static void do_waitwatch(unsigned int handle) set_timeout(); } - vec = xs_read_watch(handles[handle]); + vec = xs_read_watch(handles[handle], &num); if (!vec) { failed(handle); return; } if (handle) - output("%i:%s:%s\n", handle, vec[0], vec[1]); + output("%i:%s:%s\n", handle, + vec[XS_WATCH_PATH], vec[XS_WATCH_TOKEN]); else - output("%s:%s\n", vec[0], vec[1]); + output("%s:%s\n", vec[XS_WATCH_PATH], vec[XS_WATCH_TOKEN]); free(vec); } -- 2.30.2